
local META = FindMetaTable( "Player" )
assert( META )

-- Returns the lap the player is currently on.
function META:GetLap()
	return self:GetSyncVar( "lap_number", 1 )
end

-- Returns the checkpoint the player is currently on.
function META:GetCheckpoint()
	return self:GetSyncVar( "checkpoint_number", 0 )
end

-- Returns their best lap completion time.
function META:GetBestTime()
	return self:GetSyncVar( "best_time", 999.99 )
end

-- Returns how much time they've spent on the current lap.
function META:GetCurrentTime()
	return CurTime() - self:GetSyncVar( "lap_start_time", 0.0 )
end

-- Returns their current place.
function META:GetPlace()
	return self:GetSyncVar( "current_place", 99 )
end

function META:GetCash()
	return self:GetSyncVar( "cash", 0 )
end

function META:SetCash( cash )
	return self:SetSyncVar( "cash", cash )
end

function META:GetFakeAimVector()
	return self:GetSyncVar( "aim_vector", Vector(0,0,0) )
end

function META:SetFakeAimVector( aimvec )
	return self:SetSyncVar( "aim_vector", aimvec )
end

-- Returns whether the player has finished the race or not.
function META:HasFinished()
	return self:GetLap() > GAMEMODE:GetNumLaps()
end

function META:GetWeapon()
	return self.m_wCurWeapon
end

function META:SetWeapon( weapon )
	if CLIENT then return end

	if self:GetWeapon() then
		self:GetWeapon():Holster()
	end
	
	if not weapon then
		self.m_wCurWeapon = nil
		self:SetSyncVar( "weapon", "" )
	end
	
	local wep_class = getScriptedWeapon( weapon )
	if wep_class then
		
		self.m_wCurWeapon = wep_class:Create()
		self.m_wCurWeapon.Owner = self
		self:SetSyncVar( "weapon", weapon )
		self.m_wCurWeapon:Initialize()
		
	end
end

function META:SetMoveVelocity( vel )
	self:SetSyncVar( "move_velocity", vel )
end

function META:GetMoveVelocity( )
	return self:GetSyncVar( "move_velocity", Vector( 0,0,0 ) )
end

function META:GetLocalMoveVelocity( )
	local vel = self:GetMoveVelocity()
	local dist = vel:Length()
	local pos, ang = WorldToLocal( Vector(0,0,0), vel:Angle(), Vector(0,0,0), self:GetAngles() )
	return ang:Forward()*dist
end

function META:GetBuggyPos()
	local ang = Angle( 0,self.MoveDir,0 )
	return self:GetPos() - Vector( 0,0,1 ) + ang:Forward()*4
end

function META:GetBuggyAngle()

	if self.LastGetBuggyAngleTime == CurTime() then return self.LastGetBuggyAngle end

	local pl = self
	
	local ang = Angle( 0,self.MoveDir,0 )
		
	/* Holy fuck so many traces in a draw. */
	local trRes = util.TraceLine( { start = pl:GetPos()-ang:Forward()*3, endpos = pl:GetPos()-ang:Forward()*3-Vector(0,0,25), filter = pl } )
	local trRes2 = util.TraceLine( { start = pl:GetPos()+ang:Forward()*3, endpos = pl:GetPos()+ang:Forward()*3-Vector(0,0,25), filter = pl } )
	
	local trRes3 = util.TraceLine( { start = pl:GetPos()-ang:Right()*3, endpos = pl:GetPos()-ang:Right()*3-Vector(0,0,25), filter = pl } )
	local trRes4 = util.TraceLine( { start = pl:GetPos()+ang:Right()*3, endpos = pl:GetPos()+ang:Right()*3-Vector(0,0,25), filter = pl } )
	if trRes.Hit and trRes2.Hit then
		local locDetect = pl:WorldToLocal( trRes.HitPos )
		local locDetect2 = pl:WorldToLocal( trRes2.HitPos )
		
		local locDetect3 = pl:WorldToLocal( trRes3.HitPos )
		local locDetect4 = pl:WorldToLocal( trRes4.HitPos )
		
		local newAng = ( locDetect2 - locDetect ):Angle()
		local newAng2 = ( locDetect4 - locDetect3 ):Angle()
	
		pl.BuggyAngle = Angle(newAng.p, 0, newAng2.p) 
	end
	
	self.LastGetBuggyAngleTime = CurTime()
	self.LastGetBuggyAngle = Angle(pl.BuggyAngle.p,ang.y,pl.BuggyAngle.r)
	self.LastGetBuggyAngle:RotateAroundAxis( self.LastGetBuggyAngle:Up(), 270 )
	
	return self.LastGetBuggyAngle
	
end

function META:GetMana()
	return self:GetSyncVar( "mana", 0 )
end

function META:SetMana( mana )
	return self:SetSyncVar( "mana", mana )
end

function META:GetCarHealth()
	return self:GetSyncVar( "health", 0 )
end

function META:SetCarHealth( mana )
	return self:SetSyncVar( "health", mana )
end

function META:CarTakeDamage( damage )
	self:SetCarHealth( self:GetCarHealth() - damage )
	if self:GetCarHealth() < 0 then
		self:KillSilent()
	end
	self:SetBlinking( true )
	GAMEMODE:SetEndBlink( self, CurTime() + 0.1 )
end

if not SERVER then return end

-- Sets the player's current lap
function META:SetLap( iLap )
	self:SetSyncVar( "lap_number", iLap )
end
-- Sets the player's current checkpoint
function META:SetCheckpoint( iCheckpoint )
	self:SetSyncVar( "checkpoint_number", iCheckpoint )
	self:UpdateCheckpoint( iCheckpoint + 1 )
end
-- Sets the player's best lap time
function META:SetBestTime( fTime )
	self:SetSyncVar( "best_time", fTime )
end
-- Sets the player's current place
function META:SetPlace( iPlace )
	self:SetSyncVar( "current_place", iPlace )
end
-- No running.
olWalkSpeed = olWalkSpeed or META.SetWalkSpeed
function META:SetWalkSpeed( speed )

	olWalkSpeed( self, speed )
	self:SetRunSpeed( speed )

end
-- Is the player ready?
function META:IsReady()
	return self:GetSyncVar( "ready" )
end
function META:SetReady( bool )
	self:SetSyncVar( "ready", bool )
end

function META:UpdateCheckpoint(iCheckpoint)
	local ent = GAMEMODE.Checkpoints[iCheckpoint]
	if ValidEntity( ent ) then
		umsg.Start( "update_checkpoint", self )
			umsg.Vector(ent:LocalToWorld(ent:OBBCenter()))
			umsg.Short(iCheckpoint)
		umsg.End()
	end
end
